﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using IdleTest.MSTest;

namespace IdleTest.EFAndMVCDemo.MvcUITest
{
    public class ControllerAssert
    {
        /// <summary>
        /// 断言ViewResult
        /// </summary>
        /// <param name="view">需要断言的ActionResult对象</param>
        /// <param name="expectedModel">预期的View数据模型，null则不对View的Model断言</param>
        /// <param name="expectedViewName">预期的View名称，为空则不对View的名称断言</param>
        public static void AssertViewResult(ActionResult view, string expectedViewName, object expectedModel = null)
        {
            AssertCommon.IsInstance(typeof(ViewResult), view);
            var viewResult = view as ViewResult;

            if (!string.IsNullOrEmpty(expectedViewName))
            {
                AssertCommon.AreEqual(expectedViewName, viewResult.ViewName);
            }

            if (expectedModel != null)
            {
                AssertCommon.IsNull(false, viewResult.Model);
                AssertCommon.AreEqual(expectedModel.ToString(), viewResult.Model.ToString());
            }
        }

        /// <summary>
        /// 断言RedirectResult或与重定向相关的Action
        /// </summary>
        /// <param name="view">需要断言的ActionResult对象</param>
        /// <param name="expectedUrl">预期的重定向URL,可为绝对地址或相对地址</param>
        public static void AssertRedirectResult(ActionResult view, string expectedUrl)
        {
            if (view is ViewResult)
            {
                var result = view as ViewResult;
                int viewIndex = expectedUrl.IndexOf(result.ViewName, StringComparison.CurrentCultureIgnoreCase);
                int expectedIndex = expectedUrl.LastIndexOf("/") + 1;
                AssertCommon.AreEqual(expectedIndex, viewIndex);
            }
            else if (view is RedirectResult)
            {
                var result = view as RedirectResult;
                AssertCommon.AreEqual(expectedUrl, result.Url);
            }
            else if (view is RedirectToRouteResult)
            {
                var result = view as RedirectToRouteResult;
                string actualUrl = string.Format(
                    "/{0}/{1}", result.RouteValues["controller"], result.RouteValues["action"]);

                AssertCommon.IsBoolean(true, 
                    expectedUrl.IndexOf(actualUrl, StringComparison.CurrentCultureIgnoreCase) >= 0);
            }
            else
            {
                AssertCommon.AssertInstance.Fail(
                    string.Format("返回的View类型错误【{0}】", view));
            }
        }
    }

    public class ControllerAssertInstance : AssertInstance
    {
        public override void AreEqual<T>(T expected, T actual, bool areEqual = true, Func<T, T, bool> compareFunc = null, string message = null)
        {            
            if (expected is ContentResult)
            {
                var expectedResult = expected as ContentResult;
                var actualResult = actual as ContentResult;

                AreEqual(expectedResult.Content, actualResult.Content, areEqual);
            }
            else
            {
                base.AreEqual<T>(expected, actual, areEqual);
            }
        }
    }
}
